// 类型注解 
// java String title = '千锋教育'
// java int num = 100

// let title: string = '千锋教育'
// let num: number = 100

// 如何为对象做类型注解  ---- 接口 Interface
// 接口内部要不不写符号，要写只能写;
// interface IObj { // ObjInterface
//   username: string;
//   password: string;
//   age: number;
// }
// let obj: IObj = {
//   username: '吴大勋',
//   password: '123456',
//   age: 18
// }

// 如何为数组定义数据类型
// 数组类型注解有两种形式
//    数据类型[]
//    Array<数据类型>
// const arr: number[] = [1, 2, 3]
// const arr: Array<number> = [1, 2, 3] // Array<数据类型>  ----  泛型
// const arr: Array<string> = ['1', '2', '3']
// const arr: (number | string)[] = ['1', '2', 3] // 数组的元素 数据类型 不一致
// const arr: Array<number | string> = ['1', '2', 3] // 数组的元素 数据类型 不一致
// 那么如果数组的元素是对象呢
// interface IUser {
//   username: string;
//   sex: string
// }
// const arr: IUser[] = [
//   {
//     username: '李伟',
//     sex: '不详'
//   },
//   {
//     username: '刘强',
//     sex: '男'
//   }
// ]
// const arr: Array<IUser> = [
//   {
//     username: '李伟',
//     sex: '不详'
//   },
//   {
//     username: '刘强',
//     sex: '男'
//   }
// ]

// java public void fn () {} // 无返回值
// java public int fn () {} // 返回值为整形
// java public string fn () {} // 返回值为string
// 如果返回值为字符串等基本数据类型
// function fn (name: string, age: number): string {
//   return '123'
// }
// 如果返回值为对象呢
// interface IPro {
//   proname: string;
//   price: number
// }
// function fn (): IPro {
//   const obj = { proname: '手机', price: 999 }
//   return obj
// }
// 如果要返回的是数组呢
// 如果返回数组的元素是基本数据类型
// function fn (): number[]{
//   return [1, 2, 3]
// }
// function fn (): Array<number>{
//   return [1, 2, 3]
// }
// 如果数组的元素是对象呢
// function fn (): IPro[] {
//   return [
//     { proname: '手机', price: 999 },
//     { proname: '电脑', price: 9999 }
//   ]
// }
// function fn (): Array<IPro> {
//   return [
//     { proname: '手机', price: 999 },
//     { proname: '电脑', price: 9999 }
//   ]
// }
// 如果压根不知道到底是什么数据类型， 可以使用 ts新增数据类型 any
// let num: any;
// function fn (): any {}
// function fn (): any[] {}
// function fn (): Array<any> {}

// --------------------------以上精通，以下掌握或者了解---------------------------------------
// 如果使用函数表达式定义函数呢
// 变量的数据类型为函数
// const fn  = (): number[] => {
//   return [1, 2, 3]
// }
// const fn: Function  = (): number[] => {
//   return [1, 2, 3]
// }
// fn函数的数据类型为函数，返回值为number类型的数组 fn: () => number[]
// = 后面的是定义的函数
// => 不一定代表的就是箭头函数
// 不要混淆了 TypeScript 中的 `=>` 和 ES6 中的 `=>`。
// 在 TypeScript 的类型定义中，`=>` 用来表示函数的定义，左边是输入类型，需要用括号括起来，右边是输出类型。
// const fn: () => number[] = (): number[] => {
//   return [1, 2, 3]
// }

// 如果使用函数表达式定义函数，并且返回值为对象

// 如果数据类型为对象时，声明数据类型，只能使用接口interface吗
// 答案是 否
// 还可以使用 type
// type TPro = {
//   proname: string;
//   price: number
// }
// interface 和 type的区别在哪里，type 需要写 = 
// let obj: TPro = { proname: '手机', price: 999 }
// const fn: () => TPro[] = (): TPro[] => {
//   return [
//     { proname: '手机', price: 999 },
//     { proname: '电脑', price: 9999 }
//   ]
// }
// const fn: () => Array<TPro> = (): Array<TPro> => {
//   return [
//     { proname: '手机', price: 999 },
//     { proname: '电脑', price: 9999 }
//   ]
// }

// ---------------------如果不知道是什么数据类型，但是还不想用any - 交叉类型-------------------------------
// -----------------https://www.tslang.cn/docs/handbook/advanced-types.html-----------------
// -------------------------暂时性的放弃-----------------------
interface IPro {
  proname: string;
  price: number;
}
type TUser = {
  username: string
  id: number
}
const user: TUser = { username: '吴大勋', id: 100 }
const pro: IPro = { proname: '手机', price: 999 }
// function fn (user, pro) {
//   let result= {}
//   for(let key in user) {
//     result[key] = user[key]
//   }
//   for(let key in pro) {
//     result[key] = pro[key]
//   }
//   return result
// }
function fn<T, I> (user: T, pro: I): T & I {
  let result= <T & I>{}
  for(let key in user) {
    (<any>result)[key] = user[key]
  }
  for(let key in pro) {
    // (<any>result)[key] = pro[key]
    (result as any)[key] = pro[key]
  }
  return result
}